package neuralmusic;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;


import javax.swing.JFrame;
import javax.swing.Timer;

import neuralmusic.brain.Global;
import neuralmusic.brain.InstantScheduler;
import neuralmusic.brain.RTScheduler;
import neuralmusic.brain.ga.BrainPool;
import neuralmusic.brain.ga.Evaluator;
import neuralmusic.brain.gui.FireDisplayPanel;
import neuralmusic.brain.gui.FireRecorder;
import neuralmusic.brain.gui.NetworkDisplayPanel;
import neuralmusic.brain.module.Brain;
import neuralmusic.brain.module.Scheduler;

public class BeatLearner {

	public static void main(String args[]) throws Exception {
		new BeatLearner();

	}

	JFrame fireFrame = new JFrame();
	JFrame frame = new JFrame();
	boolean gui = true;
	boolean rt = false;

	BeatLearner() throws Exception {

		if (gui)
			makeFrames();

		BrainPool pool = new BrainPool(1, 1);

		double best = -1e6;

		while (true) {
			final Brain brain = pool.createNewBrain();
			Global.brain = brain;

			Evaluator evaluator = new Evaluator();

			Scheduler fireQueue;

			if (rt) {
				fireQueue = new RTScheduler();
				display(brain, evaluator.rec);
			} else {
				fireQueue = new InstantScheduler();
			}

			double fit = evaluator.evaluate(brain, fireQueue);

			if (!rt && gui && fit > best) {
				display(brain, evaluator.rec);
				best = fit;
				System.out.println(fit);
				repaint();
			}
		}
	}

	void repaint() {
		fireFrame.repaint();
		frame.repaint();
	}

	private void makeFrames() {

		fireFrame.setVisible(true);
		fireFrame.setLocation(350, 0);
		fireFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		fireFrame.setBounds(350, 0, 800, 300);

		frame.setSize(300, 300);
		frame.setVisible(true);
		frame.setLocation(0, 0);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		if (rt) {
			Timer t1 = new Timer(10, new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					fireFrame.repaint();
				}
			});

			Timer t2 = new Timer(100, new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					frame.repaint();
				}
			});

			t1.start();
			t2.start();
		}
	}

	private void display(Brain brain, FireRecorder rec) {

		final FireDisplayPanel fp = new FireDisplayPanel(rec);
		fireFrame.setContentPane(fp);
		fireFrame.validate();
		final NetworkDisplayPanel brainPanel = new NetworkDisplayPanel(brain);
		frame.setContentPane(brainPanel);
		frame.validate();
	}

}
